package com.awenhui.demo.core.utils.ciper;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;

/**
 * @author yuxf
 * @version 1.0
 * @date 2020/9/22 10:51
 */
public class AesUtils {
    /**
     * 加密算法
     *
     * @param password
     * @param content
     * @return
     * @throws Exception
     */
    public static String AESEncode(String content,String password) throws Exception {
        //1.构造秘钥生成器，指定秘钥算法为AES算法，这里不区分大小写
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        //2.根据password初始化秘钥生成器，生成一个128位随机源
        //这里分为多种的方式生成秘钥生成器，这里我使用的是：使用用户提供的随机源初始化此密钥生成器，使其具有确定的密钥大小。
        keyGenerator.init(128, new SecureRandom(password.getBytes()));
        //3.生成原始对称秘钥，这是一个接口类，
        SecretKey secretKey = keyGenerator.generateKey();
        //4.获得原始对称秘钥的字节数组
        byte[] secreKeyByte = secretKey.getEncoded();
        //5.根据字节数组生成AES秘钥
        SecretKey key = new SecretKeySpec(secreKeyByte, "AES");
        //6.根据指定算法AES制成密码器
        Cipher cipher = Cipher.getInstance("AES");
        //7.初始化密码器，第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作，第二个参数为使用的key
        cipher.init(Cipher.ENCRYPT_MODE, key);
        //8.获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码
        byte[] contentByte = content.getBytes("UTF-8");
        //9.使用密码器进行加密操作
        byte[] byte_AES = cipher.doFinal(contentByte);
        //10.将加密后的字符数组转成Base64的字符格式
        String key_content_base64 = Base64.getEncoder().encodeToString(byte_AES);
        return key_content_base64;
    }

    /**
     * 解密算法
     *
     * @param password
     * @param content
     * @return
     * @throws Exception
     */
    public static String AESDecode( String content,String password) throws Exception{

        //构造秘钥生成器
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        //初始化秘钥生成器
        keyGenerator.init(128, new SecureRandom(password.getBytes()));
        //生成原始对称秘钥
        SecretKey secretKey = keyGenerator.generateKey();
        //将原始对称秘钥转成byte数组
        byte[] secretKeyByte = secretKey.getEncoded();
        //根据指定算法AES和数组生成AES秘钥
        SecretKey key = new SecretKeySpec(secretKeyByte, "AES");
        //指定AES算法生成密码器      Cipher
        Cipher cipher = Cipher.getInstance("AES");
        //初始化密码器
        cipher.init(Cipher.DECRYPT_MODE, key);
        //获取Base64的字符串，进行Base64反编译
        byte[] base_Decrypt = Base64.getDecoder().decode(content);
        //使用密码器进行解密
        byte[] decrypt_byte = cipher.doFinal(base_Decrypt);
        //把数组转成string字符串
        String str = new String(decrypt_byte, "UTF-8");
        return str;
    }

    /**
     * mysql默认取秘钥的ascii编码前16位，相当于：
     *   byte[] keyBytes = Arrays.copyOf(password.getBytes("ASCII"), 16);
     *   支持：aes-128-ecb模式
     *   如果需要其它模式需要mysql5.6及以上版本才支持，可通过mysql全局变量如下方式指定：
     *      mysql> SET block_encryption_mode = 'aes-256-cbc';
     * */


    public static void main(String[] args) throws Exception {
        String hlh = AesUtils.AESEncode("何刘惠-刘丽莎-王春方-唐静","123456");
        System.out.println("加密结果："+hlh);
        String text = AESDecode(hlh,"123456");
        System.out.println("解密结果："+text);
    }
}
